home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / disk-man / mtools-3.000 / mtools-3 / mtools-3.0 / mdir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-08  |  6.9 KB  |  328 lines

  1. /*
  2.  * mdir.c:
  3.  * Display an MSDOS directory
  4.  */
  5.  
  6. #include "sysincludes.h"
  7. #include "msdos.h"
  8. #include "vfat.h"
  9. #include "mtools.h"
  10. #include "file.h"
  11. #include "streamcache.h"
  12. #include "fs.h"
  13. #include "codepage.h"
  14.  
  15.  
  16. /*
  17.  * Print an MSDOS directory date stamp.
  18.  */
  19. static inline void print_date(struct directory *dir)
  20. {
  21.     printf("%02d-%02d-%02d", DOS_MONTH(dir), DOS_DAY(dir), DOS_YEAR(dir));
  22. }
  23.  
  24. /*
  25.  * Print an MSDOS directory time stamp.
  26.  */
  27. static inline void print_time(struct directory *dir)
  28. {
  29.     char am_pm;
  30.     int hour = DOS_HOUR(dir);
  31.        
  32.     am_pm = (hour >= 12) ? 'p' : 'a';
  33.     if (hour > 12)
  34.         hour = hour - 12;
  35.     if (hour == 0)
  36.         hour = 12;
  37.  
  38.     printf("%2d:%02d%c", hour, DOS_MINUTE(dir), am_pm);
  39. }
  40.  
  41. /*
  42.  * Return a number in dotted notation
  43.  */
  44. static char *dotted_num(unsigned long num, int width, char **buf)
  45. {
  46.     int      len;
  47.     register char *srcp, *dstp;
  48.     int size;
  49.  
  50.     size = width + width;
  51.     *buf = malloc(size+1);
  52.  
  53.     if (*buf == NULL)
  54.         return "";
  55.     
  56.     /* Create the number in maximum width; make sure that the string
  57.      * length is not exceeded (in %6ld, the result can be longer than 6!)
  58.      */
  59.     sprintf(*buf, "%.*ld", size, num);
  60.  
  61.     for (srcp=*buf; srcp[1] != '\0'; ++srcp)
  62.         if (srcp[0] == '0')
  63.             srcp[0] = ' ';
  64.         else
  65.             break;
  66.     
  67.     len = strlen(*buf);
  68.     srcp = (*buf)+len;
  69.     dstp = (*buf)+len+1;
  70.  
  71.     for ( ; dstp >= (*buf)+4 && isdigit (srcp[-1]); ) {
  72.         srcp -= 3;  /* from here we copy three digits */
  73.         dstp -= 4;  /* that's where we put these 3 digits */
  74.     }
  75.  
  76.     /* now finally copy the 3-byte blocks to their new place */
  77.     while (dstp < (*buf) + len) {
  78.         dstp[0] = srcp[0];
  79.         dstp[1] = srcp[1];
  80.         dstp[2] = srcp[2];
  81.         if (dstp + 3 < (*buf) + len)
  82.             /* use spaces instead of dots: they place both
  83.              * Americans and Europeans */
  84.             dstp[3] = ' ';        
  85.         srcp += 3;
  86.         dstp += 4;
  87.     }
  88.  
  89.     return (*buf) + len-width;
  90. }
  91.  
  92. static inline void print_volume_label(Stream_t *Stream, char drive)
  93. {
  94.     DeclareThis(FsPublic_t);
  95.     Stream_t *RootDir;
  96.     int entry;
  97.     struct directory dir;
  98.     char shortname[13];
  99.     char longname[VBUFSIZE];
  100.     
  101.     /* find the volume label */
  102.     RootDir = open_root(COPY(Stream));
  103.     entry = 0;
  104.     if(vfat_lookup(RootDir, Stream, &dir, &entry, 0, 0,
  105.                ACCEPT_LABEL | MATCH_ANY,
  106.                NULL, shortname, longname, NULL) )
  107.         printf(" Volume in drive %c has no label\n", drive);
  108.     else if (*longname)
  109.         printf(" Volume in drive %c is %s (abbr=%s)\n",
  110.                drive, longname, shortname);
  111.     else
  112.         printf(" Volume in drive %c is %s\n",
  113.                drive, shortname);
  114.     if(This->serialized)
  115.         printf(" Volume Serial Number is %04lX-%04lX\n",
  116.                (This->serial_number >> 16) & 0xffff, 
  117.                This->serial_number & 0xffff);
  118.     FREE(&RootDir);
  119. }
  120.  
  121.  
  122. static inline int list_directory(Stream_t *Dir, Stream_t *Fs, char *newname, 
  123.               int wide, int all,
  124.               long *tot_size)
  125. {
  126.     int entry;
  127.     struct directory dir;
  128.     int files;
  129.     long size;
  130.     char shortname[13];
  131.     char longname[VBUFSIZE];
  132.     int i;
  133.     int Case;
  134.  
  135.     entry = 0;
  136.     files = 0;
  137.  
  138.     if(!wide)
  139.         printf("\n");
  140.  
  141.     while(vfat_lookup(Dir, Fs, &dir, &entry, 0, newname,
  142.               ACCEPT_DIR | ACCEPT_PLAIN,
  143.               NULL, shortname, longname, NULL) == 0){
  144.         if(!all && (dir.attr & 0x6))
  145.             continue;
  146.         if (wide && ! (files % 5))
  147.             putchar('\n');
  148.         files++;
  149.  
  150.         if(dir.attr & 0x10){
  151.             size = 0;
  152.         } else
  153.             size = FILE_SIZE(&dir);
  154.  
  155.         Case = dir.Case;
  156.         if(!(Case & (BASECASE | EXTCASE)) && mtools_ignore_short_case)
  157.             Case |= BASECASE | EXTCASE;
  158.  
  159.         if(Case & EXTCASE){
  160.             for(i=0; i<3;i++)
  161.                 dir.ext[i] = tolower(dir.ext[i]);
  162.         }
  163.         to_unix(dir.ext,3);
  164.         if(Case & BASECASE){
  165.             for(i=0; i<8;i++)
  166.                 dir.name[i] = tolower(dir.name[i]);
  167.         }
  168.         to_unix(dir.name,8);
  169.         if(wide){
  170.             if(dir.attr & 0x10)
  171.                 printf("[%s]%*s", shortname,
  172.                     (int) (16 - 2 - strlen(shortname)), "");
  173.             else
  174.                 printf("%-16s", shortname);
  175.         } else {                
  176.             /* is a subdirectory */
  177.             printf("%-8.8s %-3.3s ",dir.name, dir.ext);
  178.             if(dir.attr & 0x10)
  179.                 printf("<DIR>    ");
  180.             else
  181.                 printf(" %8ld", size);
  182.             printf(" ");
  183.             print_date(&dir);
  184.             printf("  ");
  185.             print_time(&dir);
  186.  
  187.             if(*longname)
  188.                 printf(" %s", longname);
  189.             printf("\n");
  190.         }
  191.         *tot_size += size;
  192.     }
  193.  
  194.     if(wide)
  195.         putchar('\n');
  196.     return files;
  197. }
  198.  
  199. static inline void print_footer(char *drive, char *newname, int files,
  200.              long tot_size, long blocks)
  201. {    
  202.     char *s1,*s2;
  203.  
  204.     if (*drive != '\0') {
  205.         if (!files)
  206.             printf("File \"%s\" not found\n"
  207.                    "                     %s bytes free\n\n",
  208.                    newname, dotted_num(blocks,12, &s1));
  209.         else {
  210.             printf("      %3d file(s)     %s bytes\n"
  211.                    "                      %s bytes free\n\n",
  212.                    files, dotted_num(tot_size,12, &s1),
  213.                    dotted_num(blocks,12, &s2));
  214.             if(s2)
  215.                 free(s2);
  216.         }
  217.         if(s1)
  218.             free(s1);
  219.     }
  220.     *drive = '\0'; /* ensure the footer is only printed once */
  221. }
  222.  
  223. void mdir(int argc, char **argv, int type)
  224. {
  225.     char *arg;
  226.     StreamCache_t sc;
  227.     int i, files, fargn, wide, all, faked;
  228.     long blocks, tot_size=0;
  229.     char last_drive;
  230.     char newpath[MAX_PATH];
  231.     char drive;
  232.     char newname[13];
  233.     Stream_t *Fs;
  234.     Stream_t *SubDir;
  235.     Stream_t *Dir;
  236.  
  237.     fargn = 1;
  238.     wide = all = files = blocks = 0;
  239.                     /* first argument */
  240.     while (argc > fargn) {
  241.         if (!strcmp(argv[fargn], "-w")) {
  242.             wide = 1;
  243.             fargn++;
  244.             continue;
  245.         }
  246.         if (!strcmp(argv[fargn], "-a")) {
  247.             all = 1;
  248.             fargn++;
  249.             continue;
  250.         }
  251.         if (argv[fargn][0] == '-') {
  252.             fprintf(stderr, "%s: illegal option -- %c\n",
  253.                 argv[0], argv[1][1]);
  254.             fprintf(stderr, "Mtools version %s, dated %s\n",
  255.                 mversion, mdate);
  256.             fprintf(stderr, "Usage: %s: [-V] [-w] [-a] msdosdirectory\n",
  257.                 argv[0]);
  258.             fprintf(stderr,
  259.             "       %s: [-V] [-w] [-a] msdosfile [msdosfiles...]\n",
  260.                 argv[0]);
  261.             cleanup_and_exit(1);
  262.         }
  263.         break;
  264.     }
  265.  
  266.     /* fake an argument */
  267.     faked = 0;
  268.     if (argc == fargn) {
  269.         faked++;
  270.         argc++;
  271.     }
  272.  
  273.     init_sc(&sc);
  274.     last_drive = '\0';
  275.     for (i = fargn; i < argc; i++) {
  276.         if (faked)
  277.             arg="";
  278.         else 
  279.             arg = argv[i];
  280.         Dir = open_subdir(&sc, arg, O_RDONLY, &Fs);
  281.         if(!Dir)
  282.             continue;
  283.         drive = sc.last_drive;
  284.  
  285.         /* is this a new device? */
  286.         if (drive != last_drive) {
  287.             print_footer(&last_drive, newname, files, tot_size,
  288.                      blocks);
  289.             blocks = getfree(Fs);
  290.             files = 0;
  291.             tot_size = 0;
  292.             print_volume_label(Fs, drive);
  293.         }
  294.         last_drive = drive;
  295.  
  296.         /*
  297.          * Under MSDOS, wildcards that match directories don't
  298.          * display the contents of that directory.  So I guess I'll
  299.          * do that too.
  300.          */
  301.         get_path(arg,newpath,sc.mcwd);
  302.         if (strpbrk(sc.filename, "*[?") == NULL &&
  303.             ((SubDir = descend(Dir, Fs, sc.filename, 0, 0) )) ) {
  304.             /* Subdirectory */            
  305.             FREE(&Dir);
  306.             Dir = SubDir;
  307.             if(*sc.filename){
  308.                 if (newpath[strlen(newpath) -1 ] != '/')
  309.                     strcat(newpath, "/");
  310.                 strcat(newpath, sc.filename);
  311.             }
  312.             *sc.filename='\0';
  313.         }
  314.  
  315.         if(sc.filename[0]=='\0')
  316.             strcpy(newname, "*");
  317.         else
  318.             strcpy(newname, sc.filename);
  319.  
  320.         printf(" Directory for %c:%s\n", drive, newpath);
  321.         files += list_directory(Dir, Fs, newname, wide, all, &tot_size);
  322.         FREE(&Dir);
  323.     }
  324.     print_footer(&last_drive, newname, files, tot_size, blocks);
  325.     finish_sc(&sc);
  326.     cleanup_and_exit(0);
  327. }
  328.